package cn.easyutil.veteran.web.handler;

import cn.easyutil.veteran.core.entity.SessionUser;
import cn.easyutil.veteran.core.logger.LogLevel;
import cn.easyutil.veteran.core.logger.LoggerUtil;
import cn.easyutil.veteran.core.utils.SpringUtils;
import cn.easyutil.veteran.web.advice.GlobalExceptionAdvice;
import cn.easyutil.veteran.web.provider.DefaultGlobalExceptionAdvice;
import cn.easyutil.veteran.web.session.SessionLogStorage;
import cn.easyutil.veteran.web.session.SessionOperation;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import java.util.List;
import java.util.Optional;

/**
 * 异常统一处理类
 */
@Component
@RestControllerAdvice
public class GlobalExceptionHandler {

    private GlobalExceptionAdvice globalExceptionAdvice;
    private final GlobalExceptionAdvice defaultAdvice = new DefaultGlobalExceptionAdvice();


    /**
     * 统一异常类返回值
     *
     * @param e 异常
     * @return 错误信息JSON字符串
     */
    @ExceptionHandler(Exception.class)
    public Object exception(Exception e) {
        if(getAdvice().printLog(e)){
            SessionUser user = SessionOperation.getUserNotException();
            SessionUser copy = new SessionUser();
            if(user != null){
                BeanUtils.copyProperties(user,copy);
            }
            String sb = "请求接口:" + SessionOperation.getRequest().getRequestURI() + "," +
                    "当前用户:" + JSONUtil.toJsonStr(copy) + "," +
                    "请求参数:" + JSONUtil.toJsonStr(Optional.ofNullable(SessionOperation.requestParams.get()).orElse(new Object())) + "," +
                    "响应参数:" + JSONUtil.toJsonStr(Optional.ofNullable(SessionOperation.responseParams.get()).orElse(new Object()));
            LoggerUtil.error(GlobalExceptionHandler.class,e, sb);
            //打印请求过程日志
            List<SessionLogStorage> logs = SessionOperation.logs.get();
            if(CollectionUtils.isNotEmpty(logs)){
                logs.forEach(log -> {
                    LogLevel level = log.getLevel();
                    if(level == LogLevel.INFO){
                        LoggerUtil.compelInfo(log.getClazz(),log.getMsg(),log.getArgs());
                    }else if(level == LogLevel.WARN){
                        LoggerUtil.compelWarn(log.getClazz(),log.getMsg(),log.getArgs());
                    }else if(level == LogLevel.DEBUG){
                        LoggerUtil.compelDebug(log.getClazz(),log.getMsg(),log.getArgs());
                    }
                });
            }
        }
        return getAdvice().packageResponse(e);
    }

    public GlobalExceptionAdvice getAdvice(){
        if(this.globalExceptionAdvice != null){
            return this.globalExceptionAdvice;
        }
        GlobalExceptionAdvice globalExceptionAdvice = SpringUtils.getBean(GlobalExceptionAdvice.class);
        if(globalExceptionAdvice == null){
            return defaultAdvice;
        }
        this.globalExceptionAdvice = globalExceptionAdvice;
        return this.globalExceptionAdvice;
    }
}
